import mongoose, { Schema, Document } from 'mongoose';

/**
 * 图书接口定义
 * 定义图书的数据结构
 */
export interface IBook extends Document {
  _id: string;
  title: string;          // 书名
  author: string;         // 作者
  publishDate: Date;      // 出版日期
  price: number;          // 价格
  isbn?: string;          // ISBN 编号（可选）
  publisher?: string;     // 出版社（可选）
  category?: string;      // 分类（可选）
  description?: string;   // 简介（可选）
  stock?: number;         // 库存（可选）
  createdAt: Date;        // 创建时间
  updatedAt: Date;        // 更新时间
}

/**
 * 图书数据模型 Schema
 * 定义 MongoDB 集合的结构和验证规则
 */
const BookSchema: Schema = new Schema(
  {
    title: {
      type: String,
      required: [true, '书名不能为空'],
      trim: true,
      maxlength: [200, '书名长度不能超过 200 个字符'],
      index: true, // 创建索引以提高查询性能
    },
    author: {
      type: String,
      required: [true, '作者不能为空'],
      trim: true,
      maxlength: [100, '作者名称长度不能超过 100 个字符'],
      index: true,
    },
    publishDate: {
      type: Date,
      required: [true, '出版日期不能为空'],
      validate: {
        validator: function(value: Date) {
          // 验证出版日期不能晚于当前日期
          return value <= new Date();
        },
        message: '出版日期不能晚于当前日期',
      },
    },
    price: {
      type: Number,
      required: [true, '价格不能为空'],
      min: [0, '价格不能为负数'],
      validate: {
        validator: function(value: number) {
          // 验证价格最多保留两位小数
          return /^\d+(\.\d{1,2})?$/.test(value.toString());
        },
        message: '价格最多保留两位小数',
      },
    },
    isbn: {
      type: String,
      trim: true,
      unique: true,
      sparse: true, // 允许多个文档的 isbn 为 null
      validate: {
        validator: function(value: string) {
          // 验证 ISBN-10 或 ISBN-13 格式
          if (!value) return true;
          const isbn10 = /^(?:\d{9}X|\d{10})$/;
          const isbn13 = /^\d{13}$/;
          return isbn10.test(value) || isbn13.test(value);
        },
        message: 'ISBN 格式不正确（应为 10 位或 13 位数字）',
      },
    },
    publisher: {
      type: String,
      trim: true,
      maxlength: [200, '出版社名称长度不能超过 200 个字符'],
    },
    category: {
      type: String,
      trim: true,
      maxlength: [50, '分类长度不能超过 50 个字符'],
      index: true,
    },
    description: {
      type: String,
      trim: true,
      maxlength: [2000, '简介长度不能超过 2000 个字符'],
    },
    stock: {
      type: Number,
      default: 0,
      min: [0, '库存不能为负数'],
    },
  },
  {
    // 自动添加 createdAt 和 updatedAt 字段
    timestamps: true,
    // 在转换为 JSON 时的配置
    toJSON: {
      virtuals: true,
      transform: function(doc, ret) {
        // 移除 __v 字段
        delete ret.__v;
        return ret;
      },
    },
    // 在转换为 Object 时的配置
    toObject: {
      virtuals: true,
    },
  }
);

/**
 * 虚拟字段：格式化后的价格
 */
BookSchema.virtual('formattedPrice').get(function(this: IBook) {
  return `¥${this.price.toFixed(2)}`;
});

/**
 * 实例方法：检查是否有库存
 */
BookSchema.methods.hasStock = function(this: IBook): boolean {
  return (this.stock || 0) > 0;
};

/**
 * 静态方法：根据作者查询图书
 */
BookSchema.statics.findByAuthor = function(author: string) {
  return this.find({ author: new RegExp(author, 'i') });
};

/**
 * 静态方法：根据分类查询图书
 */
BookSchema.statics.findByCategory = function(category: string) {
  return this.find({ category });
};

/**
 * 索引配置
 * 复合索引用于提高常用查询的性能
 */
BookSchema.index({ title: 'text', author: 'text', description: 'text' }); // 全文搜索索引
BookSchema.index({ price: 1 }); // 价格索引
BookSchema.index({ publishDate: -1 }); // 出版日期索引（降序）

/**
 * 中间件：保存前的处理
 */
BookSchema.pre('save', function(next) {
  // 可以在这里添加保存前的逻辑
  console.log('正在保存图书:', this.title);
  next();
});

/**
 * 导出图书模型
 */
export const Book = mongoose.model<IBook>('Book', BookSchema);

export default Book;
